/**
 * Copyright @ 2023 iAuto (Shanghai) Co., Ltd.
 * All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are NOT permitted except as agreed by
 * iAuto (Shanghai) Co., Ltd.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */
import { isArray, isString, cloneDeep } from 'lodash';
import BlockType from '@scene/scene-vm/src/extension-support/block-type';
import md5 from 'js-md5';
import { ACCEPT_REPORTERS } from '@/lib/blocks-vm';
import { DataType, ElementDype, filterList, SelectList } from '../dataType';
// import { secondsToTimeStr } from '@/utils';
import { Blocks, Menus, MInputArg, SkillObj } from '@/types/blocks';
// import upload from '@/assets/logo.png';
import { compareVals } from '@/utils';

// 替换占位符
const replaceAll = (str: string, args: MInputArg[], id: number): string => {
  let copyStr = str;
  if (!isArray(args)) {
    return copyStr;
  }

  // 容错解决 数字开头的
  copyStr = ' ' + copyStr;

  // 替换占位符
  args.forEach((item) => {
    copyStr = copyStr.replace(/%(d|s|f)/, ` [${item.mName}_${id}]`);
  });

  return copyStr || '';
};

// 处理 menus
const getMenus = (target: Record<string, string>, dataType: string, colors = {}): Menus => {
  // 处理特定结构
  const list = Object.entries(target).map((item) => {
    const [text, value]: [string, number] | [string, string] = item;
    // 特殊要求不用转
    // switch (dataType) {
    //   case DataType.INT:
    //   case DataType.FLOAT: {
    //     value = Number(value);
    //   }
    // }

    return {
      text,
      value,
    };
  });
  return {
    items: list,
    acceptReporters: ACCEPT_REPORTERS,
    ...colors,
  };
};

export const getType = (dataType: string): string => {
  switch (dataType) {
    case DataType.INT:
    case DataType.FLOAT:
    case DataType.DOUBLE: {
      return 'number';
    }
    case DataType.BOOL:
    case DataType.STRING: {
      return 'string';
    }
    default: {
      return 'string';
    }
  }
};

const colorMap = {
  command: {
    color1: '#5F89FF', // '#5F89FF'
    color2: '#425fb2',
    color3: '#425fb2', // 选择框背景
    color4: '#425fb2', // 边框
  },
  condition: {
    color1: '#C49ECF',
    color2: '#886e90',
    color3: '#886e90', // 选择框背景
    color4: '#886e90', // 边框
  },
};

export interface IBlockDataType {
  dataType?: string;
  elementType?: 'seekbar' | 'RGB' | 'media' | 'date' | 'date_custom' | string;
  value?: string;
  unit?: string;
  step?: number | null;
}

const a = new Set<string>();
// console.log('🚀 ~ file: index.ts ~ line 105 ~ a', a);

// skill 转化 能力blocks
export const getBlocks = (
  data: SkillObj[],
  errorBlockIds: Map<string, number[]> = new Map<string, number[]>(),
  isFilter = true
): Blocks => {
  const newData = cloneDeep(data);
  const menus = {};
  let sort = '';

  try {
    const blocks = newData.map((skill) => {
      const args = {};
      const colorObj = skill.mType === 0 ? colorMap.command : colorMap.condition;
      const dataTypeMap = {};

      if (!sort) {
        sort = skill.mSort;
      }

      // 校验异常 desc
      const regex = /%[sdf]/g;
      const matches = skill.mDesc.match(regex) || [];
      const len = matches.length;

      let suffixIconURI;

      if (isArray(skill.mInputArgs)) {
        const { length } = skill.mInputArgs;

        skill.mInputArgs.forEach((arg, index) => {
          const { mName, mDesc, _mDesc, mDefaultValue } = arg;

          let defaultValue: string | number = mDefaultValue;
          // 参数名_能力id
          const menuName = `${mName}_${skill.mID}`;

          const dataTypeInfo: IBlockDataType = {};

          if (_mDesc) {
            const [dataType, elementType, value, step, unit] = _mDesc.split(',');
            a.add(`${dataType},${elementType}`);

            if (len !== length && index >= len) {
              // console.log('error data: % length != input_args length', skill, skill.mName);
              // 收集异常字段
              // 收集占位符与实际参数不匹配id
              if (errorBlockIds.has('markIds')) {
                const markIds = errorBlockIds.get('markIds') || [];
                markIds.push(skill.mID);
                errorBlockIds.set('markIds', markIds);
              } else {
                errorBlockIds.set('markIds', [skill.mID]);
              }
            }

            // 缓存数据
            dataTypeInfo.dataType = dataType;
            dataTypeInfo.elementType = elementType;
            dataTypeInfo.value = value;
            dataTypeInfo.step = step;
            dataTypeInfo.unit = unit;

            // 统一处理
            arg.type = getType(dataType || '');

            switch (dataType) {
              // case DataType.INT:
              // case DataType.FLOAT: {
              //   defaultValue = Number(defaultValue);
              //   break;
              // }
              default: {
                defaultValue = defaultValue === '' ? ' ' : defaultValue;
                break;
              }
            }

            switch (elementType) {
              case ElementDype.RADIO:
              case ElementDype.RADIOLISTVEL:
              case ElementDype.NAVIGATION: {
                const menu = getMenus(mDesc, dataType, colorObj);
                if (elementType === ElementDype.NAVIGATION && isFilter) {
                  // 屏蔽词
                  const errorWords = ['其它', '其他']
                  menu.items = menu.items.filter((v) => !errorWords.includes(v.text));
                }
                menus[menuName] = menu;
                const itemsIndex = menu.items.findIndex((item) => item.value == defaultValue);
                if (itemsIndex === -1) {
                  defaultValue = menu.items[0].value;
                }
                arg.menu = menuName;
                break;
              }
              case ElementDype.DATE: {
                // ---------test start -------------
                // let demo = 'mm:dd hh:mm:ss';
                // defaultValue = defaultValue.slice(5)
                // value = demo;
                // ---------test end ---------------

                let newValue = value.split(' ');
                let len = newValue.length;
                if (len === 2) {
                  // 代表有日期
                  newValue[0] = newValue[0].toLocaleUpperCase(); // 转大写赋值
                  newValue[1] = newValue[1].replaceAll('h', 'H'); // h -> H
                  dataTypeInfo.value = newValue.join(' ');
                } else if (len === 1) {
                  // 一个值 得区分是不是日期 还是时间
                  if (value.includes('yyyy') || value.includes('dd')) {
                    // 判断日期
                    dataTypeInfo.value = value.toLocaleUpperCase();
                  } else if (value.includes('hh')) {
                    // 判断时间
                    dataTypeInfo.value = value.replaceAll('h', 'H');
                  } else {
                    // 不处理默认为分
                    dataTypeInfo.value = value;
                  }
                }
                break;
              }
              case ElementDype.DATE_TIMER:
              case ElementDype.TEXT: {
                if (value?.includes('~')) {
                  const valArr = value.split('~');
                  arg.max = valArr[valArr.length - 1];
                  arg.min = valArr[0];
                }
                break;
              }
              case ElementDype.MEDIA: {
                // suffixIconURI = upload;
                break;
              }
              case ElementDype.DATE_CUSTOM: {
                if (errorBlockIds.has(ElementDype.DATE_CUSTOM)) {
                  const markIds = errorBlockIds.get(ElementDype.DATE_CUSTOM) || [];
                  markIds.push(skill.mID);
                  errorBlockIds.set(ElementDype.DATE_CUSTOM, markIds);
                } else {
                  errorBlockIds.set(ElementDype.DATE_CUSTOM, [skill.mID]);
                }
                break;
              }
            }
          }

          arg.defaultValue = defaultValue;

          dataTypeMap[menuName] = dataTypeInfo;

          args[menuName] = arg;
        });
      }

      return {
        opcode: skill.mID,
        text: replaceAll(skill.mDesc, skill.mInputArgs, skill.mID),
        blockType: skill.mType === 0 ? BlockType.COMMAND : BlockType.BOOLEAN,
        arguments: args,
        args: skill.mInputArgs || [],
        type: skill.mType,
        func: 'public',
        dataType: dataTypeMap,
        suffixIconURI,
        sort: skill.mSort, // 扩展字段
        ...colorObj,
      };
    });

    // 分离 条件 动作
    const conditionBlocks: any[] = [];
    const actionBlocks: any[] = [];
    blocks.slice().forEach((block) => {
      if (block.blockType === BlockType.COMMAND) {
        actionBlocks.push(block);
      } else {
        conditionBlocks.push(block);
      }
    });

    conditionBlocks.sort((a: any, b: any) => {
      try {
        const [, aSort] = a.sort.split('.');
        const [, bSort] = b.sort.split('.');
        return compareVals(Number(aSort), Number(bSort));
      } catch (error) {
        return 0;
      }
    });

    actionBlocks.sort((a: any, b: any) => {
      try {
        const [, aSort] = a.sort.split('.');
        const [, bSort] = b.sort.split('.');
        return compareVals(Number(aSort), Number(bSort));
      } catch (error) {
        return 0;
      }
    });

    return {
      blocks: [...conditionBlocks, ...actionBlocks],
      menus,
      sort: sort,
    };
  } catch (error) {
    console.log('🚀 ~ file: index.ts ~ line 315 ~ getBlocks ~ error', error);
    return {
      blocks: [],
      menus: {},
      sort: '',
    };
  }
};

const checkErrorData = (targetData: SkillObj, isFilter: boolean): boolean => {
  const { mType, mID } = targetData;

  if (isFilter && filterList.includes(mID)){
    return false;
  }

  if (mType >= 4) {
    return false;
  }

  return true;

  // const regex = /%[sdf]/g;
  // const matches = mDesc.match(regex) || [];
  // const len = matches.length;

  // if (isArray(mInputArgs)) {
  //   const { length } = mInputArgs;

  //   if (len !== length) {
  //     console.log('error data: % length != input_args length', targetData.mID, targetData.mName);
  //     return false;
  //   }
  //   return true;
  // } else {
  //   if (len) {
  //     console.log('error data: input_args is not an array', targetData.mID, targetData.mName);
  //     return false;
  //   }
  //   return true;
  // }
};

// 处理数据
export const getSkillJson = (data: SkillObj[], isFilter = true) => {
  const newSkills = cloneDeep(data);
  const skillMap = {};
  const skillJson = newSkills
    .filter((skill) => checkErrorData(skill, isFilter))
    .map((item) => {
      skillMap [item.mID] = item;
      if (isArray(item.mInputArgs)) {
        item.mInputArgs.forEach((args) => {
          const desc = {};
          // 留存 原始 desc 数据
          args._mDesc = cloneDeep(args.mDesc);
          if (isString(args.mDesc)) {
            // 处理 desc
            const [, elementType, value] = args.mDesc.split(',');

            // 处理下拉数据
            if (SelectList.includes(elementType)) {
              const valList = value.split('*');

              if (isArray(valList)) {
                valList.forEach((val: string) => {
                  if (isString(val)) {
                    const [key, value] = val.split(':');
                    desc[key] = value;
                  }
                });
              }
            }
          }
          args.mDesc = desc;
        });
      }

      // 分割小分类
      item.mClassName = item.mClassName.split(',')[0];

      const obj = {
        category: [item.mClassName],
        id: item.mID,
      };
      return { ...item, ...obj };
    });
  return {
    skillJson,
    skillMap
  }
};

export const getCategory = (data = []) => {
  const { length } = data;

  if (isArray(data) && !length) {
    return false;
  }

  // 处理数据 防止影响其他数据
  let newData = cloneDeep(data);

  const category = {};

  newData.forEach((item) => {
    const categoryName = item.category[0];
    const categoryKey = md5(categoryName.trim());
    // const icon = findIcons(categoryName);

    if (category[categoryKey] && category[categoryKey].data) {
      category[categoryKey].data.push(item);
    } else {
      category[categoryKey] = {
        data: [item],
        name: categoryName.replaceAll('&', '&amp;'),
        zhName: categoryName.replaceAll('&', '&amp;'),
        // menuIconURI: icon.menuIcon || '',
        // blockIconURI: icon.blockIcon || '',
      };
    }
  });

  return category;
};
